I'm using Rails 5.2 with the Shrine gem for image upload. On the client side I'm using NativeScript 6.0 with Angular 8.0.
I've installed Shrine and have got it working on the Rails side and also have setup Direct image upload and tested that on the backend with Uppy and it works.
On the frontend (Android mobile) when using NativeScript I can take a photo (using nativescript-camera) and send it using nativescript-background-http to the nativescript-background-http demo server, this works.
The problem I have is getting the correct settings to send from NativeScript to Shrine.
On the backend I have these routes
Rails.application.routes.draw do
resources :asset_items
# For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html
mount ImageUploader.upload_endpoint(:cache) => "/images/upload" # POST /images/upload
end
In my shrine setup I have
require "shrine"
require "shrine/storage/file_system"
Shrine.storages = {
cache: Shrine::Storage::FileSystem.new("public", prefix: "uploads/cache"), # temporary
store: Shrine::Storage::FileSystem.new("public", prefix: "uploads"), # permanent
}
Shrine.plugin :logging, logger: Rails.logger
Shrine.plugin :upload_endpoint
Shrine.plugin :activerecord
Shrine.plugin :cached_attachment_data # for retaining the cached file across form redisplays
Shrine.plugin :restore_cached_data # re-extract metadata when attaching a cached file
#Shrine.plugin :rack_file # for non-Rails apps
On the frontend
onTakePictureTap(args) { requestPermissions().then( () => { var imageModule = require("tns-core-modules/ui/image");
takePicture({width: 150, height: 100, keepAspectRatio: true})
.then((imageAsset: any) => {
this.cameraImage = imageAsset;
let image = new imageModule.Image();
image.src = imageAsset;
this._dataItem.picture_url = this.imageAssetURL(imageAsset);
// Send picture to backend
var file = this._dataItem.picture_url;
var url = "https://192.168.1.4/images/upload";
var name = file.substr(file.lastIndexOf("/") + 1);
// upload configuration
var bghttp = require("nativescript-background-http");
var session = bghttp.session("image-upload");
var request = {
url: url,
method: "POST",
headers: {
"Content-Type": "application/octet-stream"
},
description: "Uploading " + name
};
var task = session.uploadFile(file, request);
task.on("error", this.errorHandler);
task.on("responded", this.respondedHandler);
task.on("complete", this.completeHandler);
}, (error) => {
console.log("Error: " + error);
});
},
() => alert('permissions rejected')
);
} // onTakePictureTap
The handlers look like this
errorHandler(e) {
alert("received " + e.responseCode + " code.");
var serverResponse = e.response;
}
respondedHandler(e) {
alert("received " + e.responseCode + " code. Server sent: " + e.data);
}
completeHandler(e) {
alert("received")
}
When I take a picture it tries to send it to the backend and I get the following information on the server;
Started POST "/images/upload" for 103.232.216.30 at 2019-08-14 11:14:09 +1000
Cannot render console from 103.232.216.30! Allowed networks: 127.0.0.1, ::1, 127.0.0.0/127.255.255.255
I think the problem is in the headers I'm sending to Shrine, what is the correct way of sending the image to shrine from NativeScript?
Update: Try multipartUpload
I tried the multipartUpload and also got a 400 error code
// upload configuration
var bghttp = require("nativescript-background-http");
var session = bghttp.session("image-upload");
var request = {
url: url,
method: "POST",
headers: {
"Content-Type": "application/octet-stream"
},
description: "Uploading " + name
};
var params = [
{
name: "fileToUpload.jpg",
filename: file,
mimeType: "image/jpeg"
}
];
var task = session.multipartUpload(params, request);
Update: middleware to log request
Started to put together a middleware rack class to print out the response
class MyMiddleware
def initialize(app)
@app = app
end
def call(env)
status, headers, body = @app.call(env)
puts "Middleware called. Status: #{status}, Headers: #{headers}"
[status, headers, body]
end
end
When I send a file, it sends the response
Middleware called. Status: 400, Headers: {"Content-Type"=>"text/plain", "Content-Length"=>"16"}
Having a look at headers,status and body in byebug when sending from NativeScript;
(byebug) headers
{"Content-Type"=>"text/plain", "Content-Length"=>"16", "Cache-Control"=>"no-cache", "X-Request-Id"=>"7a5d40e2-5c09-4fc7-88b5-83813cedf20e", "X-Runtime"=>"0.055892"}
(byebug) status
400
(byebug) body
#<Rack::BodyProxy:0x000056471192c580 @body=#<Rack::BodyProxy:0x000056471192c620 @body=#<Rack::BodyProxy:0x000056471192c878 @body=#<Rack::BodyProxy:0x000056471192c968 @body=#<Rack::BodyProxy:0x000056471192cdc8 @body=["Upload Not Found"], @block=#<Proc:0x000056471192cd28@/usr/local/rbenv/versions/2.6.2/lib/ruby/gems/2.6.0/gems/rack-2.0.7/lib/rack/tempfile_reaper.rb:16>, @closed=false>, @block=#<Proc:0x000056471192c918@/usr/local/rbenv/versions/2.6.2/lib/ruby/gems/2.6.0/gems/actionpack-5.2.3/lib/action_dispatch/middleware/executor.rb:15>, @closed=false>, @block=#<Proc:0x000056471192c850@/usr/local/rbenv/versions/2.6.2/lib/ruby/gems/2.6.0/gems/railties-5.2.3/lib/rails/rack/logger.rb:39>, @closed=false>, @block=#<Proc:0x000056471192c5d0@/usr/local/rbenv/versions/2.6.2/lib/ruby/gems/2.6.0/gems/activesupport-5.2.3/lib/active_support/cache/strategy/local_cache_middleware.rb:30>, @closed=false>, @block=#<Proc:0x000056471192c508@/usr/local/rbenv/versions/2.6.2/lib/ruby/gems/2.6.0/gems/actionpack-5.2.3/lib/action_dispatch/middleware/executor.rb:15>, @closed=false>
A successful send via Uppy on the Rails side shows this result
(byebug) status
200
(byebug) headers
{"Content-Type"=>"application/json; charset=utf-8", "Content-Length"=>"149", "ETag"=>"W/\"29040a3f35783193f7ba450aac8906bd\"", "Cache-Control"=>"max-age=0, private, must-revalidate", "X-Request-Id"=>"53b380b8-e902-49d3-885f-634fc9ea82dc", "X-Runtime"=>"0.028117"}
(byebug) body
#<Rack::BodyProxy:0x00007f2c801f8868 @body=#<Rack::BodyProxy:0x00007f2c801f8980 @body=#<Rack::BodyProxy:0x00007f2c801f8de0 @body=#<Rack::BodyProxy:0x00007f2c801f90b0 @body=#<Rack::BodyProxy:0x00007f2c801f98f8 @body=["{\"id\":\"85bf685af3b7965c701227478e2189a2.jpg\",\"storage\":\"cache\",\"metadata\":{\"filename\":\"DSCF3107_edited.JPG\",\"size\":3998332,\"mime_type\":\"image/jpeg\"}}"], @block=#<Proc:0x00007f2c801f9858@/usr/local/rbenv/versions/2.6.2/lib/ruby/gems/2.6.0/gems/rack-2.0.7/lib/rack/etag.rb:30>, @closed=false>, @block=#<Proc:0x00007f2c801f8f98@/usr/local/rbenv/versions/2.6.2/lib/ruby/gems/2.6.0/gems/actionpack-5.2.3/lib/action_dispatch/middleware/executor.rb:15>, @closed=false>, @block=#<Proc:0x00007f2c801f8db8@/usr/local/rbenv/versions/2.6.2/lib/ruby/gems/2.6.0/gems/railties-5.2.3/lib/rails/rack/logger.rb:39>, @closed=false>, @block=#<Proc:0x00007f2c801f8890@/usr/local/rbenv/versions/2.6.2/lib/ruby/gems/2.6.0/gems/activesupport-5.2.3/lib/active_support/cache/strategy/local_cache_middleware.rb:30>, @closed=false>, @block=#<Proc:0x00007f2c801f8750@/usr/local/rbenv/versions/2.6.2/lib/ruby/gems/2.6.0/gems/actionpack-5.2.3/lib/action_dispatch/middleware/executor.rb:15>, @closed=false>
Info from Chrome Network on Successful upload via Uppy
- General
: Request URL: http://localhost:9000/images/upload
: Request Method: POST
: Status Code: 200 OK
: Remote Address: [::1]:9000
: Referrer Policy: strict-origin-when-cross-origin
- Response
: Cache-Control: max-age=0, private, must-revalidate
: Content-Length: 141
: Content-Type: application/json; charset=utf-8
: ETag: W/"8e3a470866888e1d724013e95d0a49b4"
: X-Request-Id: 3e4222bd-e5bf-4270-bc31-1fc2c25696b1
: X-Runtime: 0.010884
- Request
: Accept: */*
: Accept-Encoding: gzip, deflate, br
: Accept-Language: en-US,en;q=0.9
: Cache-Control: no-cache
: Connection: keep-alive
: Content-Length: 110221
: Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryBRJtv5UR0QTM2J2x
: Cookie: _session_id=73b3a497c62bd745a789bc00b9f14361; org.cups.sid=c9eb7594a0515f4965b7a8e2f7900050; io=aArI7Q_64r2LWkc5AAAA; CSRF-Token-4MYJC=hLjA49c9bSsUhMUrYMfgSFSEnquQufo3; CSRF-Token-CAGDA=53tpJXxkvAstfeCoAKKbWgQDiQpU7xLj; CSRF-Token-TUFRR=kAWjSsQW4YCdEyGtaNKpfPT4gjToabYL; XSRF-TOKEN=HCjw%2B3WTJcSd1ddt45JGGGo8Uer43ggZZRrcsLc2NFgTdghJ852fqo0rWUx0%2FfBIOfv9YEMJ7mXw8TCix7d2cA%3D%3D; CSRF-Token-XDZDE=LyXXMXei6ci6FHrE3MfTxn3ARAKXYgMZ; _personal_property_rails_prototype_session=u65TkCvL9slUmGQQsP37lJH0BPcMw0E5%2FaDNw6frbuFw8NwqfM9gYPp%2F%2F830NFeZJqwxnYqc%2FCP%2FPIXhvPGFbD4waESKMKS1ChILCxTXZAPRFFULtu9m4Xl2G6AlF0ZamkzY7sdcE15vnpIBm8M%3D--98yhZGLNKsL5dnSX--Radl4qCShjACiTHc5UTH1A%3D%3D
: Host: localhost:9000
: Origin: http://localhost:9000
: Pragma: no-cache
: Referer: http://localhost:9000/asset_items/new
: User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36
- Form data
: name: 2014-mlug.png
: type: image/png
: files[]: (binary)
from Upload to Rails Shrine from NativeScript
No comments:
Post a Comment