Звучит так, будто вы хотите загрузить файл в свою функцию Azure с помощью Http Trigger в Java через HTML-форму с multipart/form-data
, как показано ниже.
<form method="POST" enctype="multipart/form-data" action="https://<your function app>/api/HttpTrigger-Java">
File to upload: <input type="file" name="upfile"><br/>
Notes about the file: <input type="text" name="note"><br/>
<br/>
<input type="submit" value="Press"> to upload the file!
</form>
Однако ни один класс не реализуетинтерфейс HttpRequestMessage<T>
и, кажется, не приводит HttpRequestMessage
к HttpServletRequest
после того, как я исследовал исходный код GitHub Repo Azure/azure-functions-java-library
.
По моему опыту, единственный способ - проанализировать заголовок и тело запроса multipart/form-data
, чтобы получить файл.Есть ответ на аналогичную ветку SO Библиотека и примеры анализа multipart / form-data из inputtream , опубликованные владельцем вопроса, который включает код с использованием MultipartStream
класса Apache Commons FileUpload , который работает после того, как я его протестировал.
Вот заголовок Content-Type
и тело запроса multipart/form-data
, полученного из функции Azure для Java.
Заголовок Content-Type
content-type: multipart/form-data; boundary=----WebKitFormBoundaryT2TWuevX3RIYWRQF
multipart/form-data
тело запроса
------WebKitFormBoundaryT2TWuevX3RIYWRQF
Content-Disposition: form-data; name="upfile"; filename="z.txt"
Content-Type: text/plain
1234
ABCD
------WebKitFormBoundaryT2TWuevX3RIYWRQF
Content-Disposition: form-data; name="note"
test.txt
------WebKitFormBoundaryT2TWuevX3RIYWRQF--
Вот мой пример кода для извлечения файла.
@FunctionName("HttpTrigger-Java")
public HttpResponseMessage run(
@HttpTrigger(name = "req", methods = {HttpMethod.GET, HttpMethod.POST}, authLevel = AuthorizationLevel.ANONYMOUS) HttpRequestMessage<Optional<String>> request,
final ExecutionContext context) {
String contentType = request.getHeaders().get("content-type"); // Get content-type header
// here the "content-type" must be lower-case
String body = request.getBody().get(); // Get request body
InputStream in = new ByteArrayInputStream(body.getBytes()); // Convert body to an input stream
String boundary = contentType.split(";")[1].split("=")[1]; // Get boundary from content-type header
int bufSize = 1024;
MultipartStream multipartStream = new MultipartStream(in, boundary.getBytes(), bufSize, null); // Using MultipartStream to parse body input stream
// the code below comes from the SO thread above
// you can fetch a file content from readBodyData
// after the headers Content-Disposition: form-data; name="upfile"; filename="test.txt" \n Content-Type: text/plain
boolean nextPart = multipartStream.skipPreamble();
while (nextPart) {
String header = multipartStream.readHeaders();
System.out.println("");
System.out.println("Headers:");
System.out.println(header);
System.out.println("Body:");
multipartStream.readBodyData(System.out);
System.out.println("");
nextPart = multipartStream.readBoundary();
}
return request.createResponseBuilder(HttpStatus.OK).body("Success").build();
}
Вывод кода выше в терминале:
Headers:
Content-Disposition: form-data; name="upfile"; filename="test.txt"
Content-Type: text/plain
Body:
1234
ABCD
Headers:
Content-Disposition: form-data; name="note"
Body:
test.txt
Обновление: при загрузке изображения вывод кода выше будет таким, как показано ниже.
Headers:
Content-Disposition: form-data; name="upfile"; filename="test.jpg"
Content-Type: image/png
Body:
<the binary content of an image>
Таким образом, вы можете проанализировать заголовок, чтобы получить значение filename
и использовать FileOutputStream
для его сохранения, как показано ниже.
while(nextPart) {
String header = multipartStream.readHeaders();
System.out.println("");
System.out.println("Headers:");
System.out.println(header);
System.out.println("Body:");
if (header.contains("Content-Type: image/")) {
int start = header.indexOf("filename=")+"filename=".length()+1;
int end = header.indexOf("\r\n")-1;
String filename = header.substring(start, end);
System.out.println(filename);
FileOutputStream fos = new FileOutputStream(filename);
multipartStream.readBodyData(fos);
} else {
multipartStream.readBodyData(System.out);
}
System.out.println("");
nextPart = multipartStream.readBoundary();
}
Обновление 2:
Я обнаружил, что существует проблема Azure Function for Java, которая может быть ошибкой, которая приводит к потере некоторых байтов при загрузке двоичного файла, ноэто не произойдет при загрузке текстового файла.Поэтому обходным решением является преобразование файла загрузки в строку base64 в браузере для публикации в функцию Azure и преобразование содержимого base64, загруженного в двоичный файл источника в функции Azure.
Вот мой тестовый HTML-код.
File to upload: <input type="file" name="upfile" id="fileup"><br/>
<form method="POST" enctype="multipart/form-data" action="http://localhost:7071/api/HttpTrigger-Java">
Notes about the file: <input type="text" name="note"><br/>
<input type="hidden" name="file_base64" id="file_base64"><br/>
<input type="submit" value="Press"> to upload the file!
</form>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js">/script>
<script>
$(document).ready(function(){
$("#fileup").change(function(){
var v = $(this).val();
var reader = new FileReader();
reader.readAsDataURL(this.files[0]);
reader.onload = function(e){
console.log(e.target.result);
$('#file_base64').val(e.target.result);
};
});
});
</script>
В приведенной выше форме будут размещены заголовок и тело фрагмента файла base64, как показано ниже.
Header:
Content-Disposition: form-data; name="file_base64"
Body:
data:image/jpg;base64,iVBORw0KGgoAAAANSUhEUgAAB.............
Мой код Java в Azure Функция:
import java.io.ByteArrayOutputStream;
import java.util.Base64;
if (header.equals("Content-Disposition: form-data; name=\"file_base64\"")) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
multipartStream.readBodyData(baos);
String content = baos.toString();
// System.out.println(content);
int index = content.indexOf(",")+1; // Get the index of base64 string in data-uploaded string
byte[] imgBytes = Base64.getDecoder().decode(content.substring(index)); // convert image base64 string to image byte arrays
....
// To upload image byte array to Blob Storage
// You can get the upload image filename from the form input `note`, please notes the order of form input elements.
} else {
multipartStream.readBodyData(System.out);
}