Gre*_*egg 687 rest grails json file-upload
这可能是一个愚蠢的问题,但我有一个晚上.在我正在开发RESTful API的应用程序中,我们希望客户端以JSON格式发送数据.此应用程序的一部分要求客户端上载文件(通常是图像)以及有关图像的信息.
我很难跟踪单个请求中如何发生这种情况.是否可以将文件数据Base64转换为JSON字符串?我是否需要向服务器发送2个帖子?我不应该为此使用JSON吗?
作为旁注,我们在后端使用Grails,这些服务由本机移动客户端(iPhone,Android等)访问,如果其中任何一个有所不同.
Dan*_* T. 575
我在这里问了一个类似的问题:
你基本上有三个选择:
multipart/form-data
POST中发送文件,然后将ID返回给客户端.然后,客户端发送带有ID的元数据,服务器将文件和元数据重新关联.McS*_*tch 97
您可以使用multipart/form-data 内容类型在一个请求中发送文件和数据:
在许多应用中,可以向用户呈现表格.用户将填写表单,包括键入的信息,由用户输入生成的信息,或者包含在用户选择的文件中的信息.填写表单后,表单中的数据将从用户发送到接收应用程序.
MultiPart/Form-Data的定义来自其中一个应用程序......
来自http://www.faqs.org/rfcs/rfc2388.html:
"multipart/form-data"包含一系列部分.每个部分都应包含内容处置标题[RFC 2183],其中处置类型为"form-data",并且处置包含"name"的(附加)参数,其中该参数的值为原始值表单中的字段名称.例如,部件可能包含标头:
内容处理:表格数据; 名称="用户"
具有与"user"字段的条目对应的值.
您可以在边界之间的每个部分中包含文件信息或字段信息.我已经成功实现了RESTful服务,该服务要求用户提交数据和表单,并且multipart/form-data完美地工作.该服务是使用Java/Spring构建的,客户端使用的是C#,所以很遗憾,我没有任何Grails示例可以为您提供有关如何设置服务的信息.在这种情况下,您不需要使用JSON,因为每个"form-data"部分都为您提供了指定参数名称及其值的位置.
使用multipart/form-data的好处在于您使用的是HTTP定义的头文件,因此您坚持使用现有HTTP工具创建服务的REST理念.
pgi*_*cek 44
我知道这个帖子很老了,但是,我在这里缺少一个选项.如果您要将要发送的元数据(以任何格式)与要上载的数据一起发送,则可以发出单个multipart/related
请求.
Multipart/Related媒体类型适用于由多个相互关联的身体部位组成的复合对象.
您可以查看RFC 2387规范以获取更深入的详细信息.
基本上,这种请求的每个部分可以具有不同类型的内容,并且所有部分都以某种方式相关(例如,图像和它的元数据).部件由边界字符串标识,最后的边界字符串后跟两个连字符.
例:
POST /upload HTTP/1.1
Host: www.hostname.com
Content-Type: multipart/related; boundary=xyz
Content-Length: [actual-content-length]
--xyz
Content-Type: application/json; charset=UTF-8
{
"name": "Sample image",
"desc": "...",
...
}
--xyz
Content-Type: image/jpeg
[image data]
[image data]
[image data]
...
--foo_bar_baz--
Run Code Online (Sandbox Code Playgroud)
小智 14
我知道这个问题已经过时了,但在最后几天我搜索了整个网络以解决同样的问题.我有grails REST webservices和iPhone Client发送图片,标题和描述.
我不知道我的方法是否最好,但是如此简单易行.
我使用UIImagePickerController拍照并使用请求的标头标签向服务器发送NSData以发送图片的数据.
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:[NSURL URLWithString:@"myServerAddress"]];
[request setHTTPMethod:@"POST"];
[request setHTTPBody:UIImageJPEGRepresentation(picture, 0.5)];
[request setValue:@"image/jpeg" forHTTPHeaderField:@"Content-Type"];
[request setValue:@"myPhotoTitle" forHTTPHeaderField:@"Photo-Title"];
[request setValue:@"myPhotoDescription" forHTTPHeaderField:@"Photo-Description"];
NSURLResponse *response;
NSError *error;
[NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];
Run Code Online (Sandbox Code Playgroud)
在服务器端,我使用以下代码收到照片:
InputStream is = request.inputStream
def receivedPhotoFile = (IOUtils.toByteArray(is))
def photo = new Photo()
photo.photoFile = receivedPhotoFile //photoFile is a transient attribute
photo.title = request.getHeader("Photo-Title")
photo.description = request.getHeader("Photo-Description")
photo.imageURL = "temp"
if (photo.save()) {
File saveLocation = grailsAttributes.getApplicationContext().getResource(File.separator + "images").getFile()
saveLocation.mkdirs()
File tempFile = File.createTempFile("photo", ".jpg", saveLocation)
photo.imageURL = saveLocation.getName() + "/" + tempFile.getName()
tempFile.append(photo.photoFile);
} else {
println("Error")
}
Run Code Online (Sandbox Code Playgroud)
我不知道将来是否有问题,但现在在生产环境中工作正常.
这是我的方法API(我使用示例) - 正如您所看到的,您在API中不使用任何file_id(在服务器中上传的文件identyicator):
1.在服务器上创建"照片"对象:
POST: /projects/{project_id}/photos
params in: {name:some_schema.jpg, comment:blah}
return: photo_id
Run Code Online (Sandbox Code Playgroud)
2.上传文件(注意'文件'是单数形式,因为每张照片只有一个):
POST: /projects/{project_id}/photos/{photo_id}/file
params in: file to upload
return: -
Run Code Online (Sandbox Code Playgroud)
然后例如:
3.阅读照片列表
GET: /projects/{project_id}/photos
params in: -
return: array of objects: [ photo, photo, photo, ... ]
Run Code Online (Sandbox Code Playgroud)
4.阅读一些照片细节
GET: /projects/{project_id}/photos/{photo_id}
params in: -
return: photo = { id: 666, name:'some_schema.jpg', comment:'blah'}
Run Code Online (Sandbox Code Playgroud)
5.阅读照片文件
GET: /projects/{project_id}/photos/{photo_id}/file
params in: -
return: file content
Run Code Online (Sandbox Code Playgroud)
所以结论是,首先你通过POST创建对象(照片),然后你发送带文件的secod请求(再次POST).
由于唯一缺少的例子是ANDROID示例,我将添加它.此技术使用应在Activity类中声明的自定义AsyncTask.
private class UploadFile extends AsyncTask<Void, Integer, String> {
@Override
protected void onPreExecute() {
// set a status bar or show a dialog to the user here
super.onPreExecute();
}
@Override
protected void onProgressUpdate(Integer... progress) {
// progress[0] is the current status (e.g. 10%)
// here you can update the user interface with the current status
}
@Override
protected String doInBackground(Void... params) {
return uploadFile();
}
private String uploadFile() {
String responseString = null;
HttpClient httpClient = new DefaultHttpClient();
HttpPost httpPost = new HttpPost("http://example.com/upload-file");
try {
AndroidMultiPartEntity ampEntity = new AndroidMultiPartEntity(
new ProgressListener() {
@Override
public void transferred(long num) {
// this trigger the progressUpdate event
publishProgress((int) ((num / (float) totalSize) * 100));
}
});
File myFile = new File("/my/image/path/example.jpg");
ampEntity.addPart("fileFieldName", new FileBody(myFile));
totalSize = ampEntity.getContentLength();
httpPost.setEntity(ampEntity);
// Making server call
HttpResponse httpResponse = httpClient.execute(httpPost);
HttpEntity httpEntity = httpResponse.getEntity();
int statusCode = httpResponse.getStatusLine().getStatusCode();
if (statusCode == 200) {
responseString = EntityUtils.toString(httpEntity);
} else {
responseString = "Error, http status: "
+ statusCode;
}
} catch (Exception e) {
responseString = e.getMessage();
}
return responseString;
}
@Override
protected void onPostExecute(String result) {
// if you want update the user interface with upload result
super.onPostExecute(result);
}
}
Run Code Online (Sandbox Code Playgroud)
所以,当你想上传你的文件时,只需致电:
new UploadFile().execute();
Run Code Online (Sandbox Code Playgroud)
FormData对象:使用Ajax上传文件
XMLHttpRequest Level 2增加了对新FormData接口的支持.FormData对象提供了一种方法,可以轻松构造一组表示表单字段及其值的键/值对,然后可以使用XMLHttpRequest send()方法轻松发送.
function AjaxFileUpload() {
var file = document.getElementById("files");
//var file = fileInput;
var fd = new FormData();
fd.append("imageFileData", file);
var xhr = new XMLHttpRequest();
xhr.open("POST", '/ws/fileUpload.do');
xhr.onreadystatechange = function () {
if (xhr.readyState == 4) {
alert('success');
}
else if (uploadResult == 'success')
alert('error');
};
xhr.send(fd);
}
Run Code Online (Sandbox Code Playgroud)
https://developer.mozilla.org/en-US/docs/Web/API/FormData
归档时间: |
|
查看次数: |
549713 次 |
最近记录: |